package com.zh.note.demo.juc;

import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.threadpool.TtlExecutors;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * ThreadLocal
 * inheritableThreadLocal 线程间数据传递：允许父线程创建的变量能够被子线程继承
 * TransmittableThreadLocal 。它解决了线程池中 inheritableThreadLocal 值无法传递的问题，能够在父子线程间自动传递上下文信息
 */
@Slf4j
public class ThreadLocalLocalDemo4 {
    public static void main(String[] args) {
//        m1();
//        m2();
//        m3();
        m4();
    }

    public static void m1() {
        ThreadLocal<String> threadLocal = ThreadLocal.withInitial(() -> null);

        threadLocal.set("[" + Thread.currentThread().getName() + "-java]");
        log.info("major: {}", threadLocal.get());

        // 新建线程thread1, 设置vue
        new Thread(() -> {
            log.info("major: {}", threadLocal.get()); // thread1是否可以取得main线程写入的值
            threadLocal.set("[" + Thread.currentThread().getName() + "-Vue]");
            log.info("major: {}", threadLocal.get());
        }, "thread1").start();

        new Thread(() -> {
            log.info("major: {}", threadLocal.get()); // thread2是否可以取得main线程写入的值
            threadLocal.set("[" + Thread.currentThread().getName() + "-Flink]");
            log.info("major: {}", threadLocal.get());
        }, "thread2").start();

        CompletableFuture.supplyAsync(() -> {
            log.info("major: {}", threadLocal.get());
            threadLocal.set("[" + Thread.currentThread().getName() + "-mysql]");
            log.info("major: {}", threadLocal.get());
            return null;
        });

    }

    public static void m2() {
        // 子线程都可以获取main线程写入的值
        InheritableThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>();

        inheritableThreadLocal.set("[" + Thread.currentThread().getName() + "-java]");
        log.info("major: {}", inheritableThreadLocal.get());

        // 新建线程thread1
        new Thread(() -> {
            log.info("major: {}", inheritableThreadLocal.get()); // thread1是否可以取得main线程写入的值
        }, "thread1").start();

        new Thread(() -> {
            log.info("major: {}", inheritableThreadLocal.get()); // thread2是否可以取得main线程写入的值
        }, "thread2").start();

        new Thread(() -> {
            log.info("major: {}", inheritableThreadLocal.get()); // thread3是否可以取得main线程写入的值
        }, "thread3").start();
    }

    public static void m3() {

        //InheritableThreadLocal 遇到线程池会有问题
        InheritableThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>();

        inheritableThreadLocal.set("[" + Thread.currentThread().getName() + "-java]");
        log.info("major: {}", inheritableThreadLocal.get());

        ExecutorService threadPool = Executors.newFixedThreadPool(1);
        threadPool.execute(() -> {
            log.info("threadPool第一次获取 major:{}", inheritableThreadLocal.get());
        });
        // 主线程修改值
        inheritableThreadLocal.set("[" + Thread.currentThread().getName() + "-vue 修改了]");
        log.info("major: {}", inheritableThreadLocal.get());
        // 这里又在线程池中inheritableThreadLocal.get()方法拿值，会获取不到修改后的值
        threadPool.execute(() -> {
            log.info("threadPool第二次获取 major:{}", inheritableThreadLocal.get());
        });
        threadPool.shutdown();

    }

    public static void m4() {

        TransmittableThreadLocal<String> transmittableThreadLocal = new TransmittableThreadLocal<>();

        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        threadPool = TtlExecutors.getTtlExecutorService(threadPool);

        transmittableThreadLocal.set("[" + Thread.currentThread().getName() + "-java]");
        log.info("major: {}", transmittableThreadLocal.get());

        threadPool.execute(() -> {
            log.info("threadPool第一次获取 major:{}", transmittableThreadLocal.get());
        });
        // 主线程修改值
        transmittableThreadLocal.set("[" + Thread.currentThread().getName() + "-vue 线程池修改了]");
        threadPool.execute(() -> {
            log.info("threadPool第二次获取 major:{}", transmittableThreadLocal.get());
        });

        threadPool.shutdown();


    }
}
